package com.dlc.shop.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.binarywang.wxpay.bean.merchanttransfer.TransferCreateRequest;
import com.github.binarywang.wxpay.bean.merchanttransfer.TransferCreateResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.dlc.shop.bean.event.EnterprisePayFailEvent;
import com.dlc.shop.bean.event.EnterprisePaySuccessEvent;
import com.dlc.shop.bean.model.EnterprisePay;
import com.dlc.shop.bean.model.User;
import com.dlc.shop.common.bean.WxMiniApp;
import com.dlc.shop.common.constants.SegmentIdKey;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.common.util.Arith;
import com.dlc.shop.config.ShopConfig;
import com.dlc.shop.config.WxConfig;
import com.dlc.shop.dao.EnterprisePayMapper;
import com.dlc.shop.service.EnterprisePayService;
import com.dlc.shop.service.SegmentService;
import com.dlc.shop.service.UserService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @author
 * @date 2019-10-15 16:44:50
 */
@Slf4j
@Service
@AllArgsConstructor
public class EnterprisePayServiceImpl extends ServiceImpl<EnterprisePayMapper, EnterprisePay> implements EnterprisePayService {

    private final EnterprisePayMapper enterprisePayMapper;
    private final ApplicationContext applicationContext;
    private static final String CLIENT_IP = "127.0.0.1";
    private final WxConfig wxConfig;
    private final ShopConfig shopConfig;
    private final SegmentService segmentService;
    private final UserService userService;

    @Override
    public List<EnterprisePay> listApplyEnterprisePay() {
        return enterprisePayMapper.listApplyEnterprisePay();
    }

    @Override
    public List<EnterprisePay> listEnterprisePay() {
        return enterprisePayMapper.listEnterprisePay();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sendEnterprisePay(List<EnterprisePay> enterprisePayList) {
        if (CollectionUtils.isEmpty(enterprisePayList)) {
            return;
        }
        String outBatchNo = String.valueOf(segmentService.getDateFormatSegmentId(SegmentIdKey.PAY));
        TransferCreateRequest transferCreateRequest = new TransferCreateRequest();
        WxMiniApp wxMiniApp = shopConfig.getWxMiniApp();
        transferCreateRequest.setAppid(wxMiniApp.getAppId());
        transferCreateRequest.setOutBatchNo(outBatchNo);
        transferCreateRequest.setBatchName("NO_CHECK");
        // 批次备注
        transferCreateRequest.setBatchRemark("商城分销提现");
        List<TransferCreateRequest.TransferDetailList> transferDetailList = new ArrayList<>();
        int totalAmount = 0;
        Set<String> userIds = enterprisePayList.stream().map(EnterprisePay::getUserId).collect(Collectors.toSet());
        Map<String, User> userMap = userService.getUserListByUserNumbers(userIds);
        for (EnterprisePay enterprisePay : enterprisePayList) {
            TransferCreateRequest.TransferDetailList transferDetail = new TransferCreateRequest.TransferDetailList();
            transferDetail.setOpenid(enterprisePay.getOpenId());
            transferDetail.setOutDetailNo(String.valueOf(enterprisePay.getEntPayOrderNo()));
            int amout = (int) Arith.mul(enterprisePay.getAmount(), 100.0);
            transferDetail.setTransferAmount(amout);
            User user = userMap.get(enterprisePay.getUserId());
            // 转账备注
            if (Objects.isNull(user)) {
                transferDetail.setTransferRemark("分销用户已注销");
            } else {
                transferDetail.setTransferRemark(user.getNickName() + "(" + user.getUserMobile() + ")");
            }
            transferDetailList.add(transferDetail);
            totalAmount += amout;
        }
        transferCreateRequest.setTotalAmount(totalAmount);
        transferCreateRequest.setTotalNum(enterprisePayList.size());
        transferCreateRequest.setTransferDetailList(transferDetailList);
        try {
            TransferCreateResult transfer = wxConfig.getMerchantTransferService().createTransfer(transferCreateRequest);
            enterprisePayList.forEach(enterprisePay -> {
                enterprisePay.setOutBatchNo(transfer.getOutBatchNo());
            });
            updateBatch(enterprisePayList);
        } catch (WxPayException wxPayException) {
            wxPayException.printStackTrace();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void paySuccess(EnterprisePay enterprisePay) {
        //更新商家转账信息
        if (enterprisePayMapper.paySuccess(enterprisePay.getEntPayOrderNo(), enterprisePay.getVersion()) != 1) {
            // 更新余额记录失败，请稍后再试
            throw new YamiShopBindException("yami.shop.update.balance");
        }
        // 推送支付成功事件
        applicationContext.publishEvent(new EnterprisePaySuccessEvent(enterprisePay));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void payFailed(EnterprisePay enterprisePay) {
        //更新商家转账信息
        if (enterprisePayMapper.payFailed(enterprisePay.getEntPayOrderNo(), enterprisePay.getVersion()) != 1) {
            // 更新余额记录失败，请稍后再试
            throw new YamiShopBindException("yami.shop.update.balance");
        }
        // 推送支付失败事件
        applicationContext.publishEvent(new EnterprisePayFailEvent(enterprisePay));

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBatch(List<EnterprisePay> enterprisePayList) {
        enterprisePayMapper.updateBatch(enterprisePayList);
    }
}
